home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / languags / a68k242.2 < prev    next >
Text File  |  1989-03-08  |  63KB  |  2,071 lines

  1. Path: xanth!lll-winken!ames!mailrus!bbn!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i024:  a68k - 68000 assembler v2.42, Part02/04
  5. Message-ID: <12035@swan.ulowell.edu>
  6. Date: 8 Mar 89 01:48:29 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2060
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: jlydiatt@jlami.wimsey.bc.ca (Jeff Lydiatt)
  12. Posting-number: Volume 89, Issue 24
  13. Archive-name: languages/a68k242.2
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    A68kmisc.c
  23. #    History.log
  24. #    A68k2do.txt
  25. #    Makefile
  26. #    Makefile.azt
  27. #    Makefile.dbg
  28. #    Makefile.pdc
  29. #    wb_parse.c
  30. # This archive created: Tue Mar  7 20:40:28 1989
  31. cat << \SHAR_EOF > A68kmisc.c
  32. /*------------------------------------------------------------------*/
  33. /*                                    */
  34. /*              MC68000 Cross Assembler                */
  35. /*                                    */
  36. /*          Copyright    (c) 1985 by Brian R. Anderson            */
  37. /*                                    */
  38. /*          Miscellaneous routines - January 6, 1989            */
  39. /*                                    */
  40. /*   This program may be copied    for personal, non-commercial use    */
  41. /*   only, provided that the above copyright notice is included        */
  42. /*   on    all copies of the source code.    Copying    for any    other use   */
  43. /*   without the consent of the    author is prohibited.            */
  44. /*                                    */
  45. /*------------------------------------------------------------------*/
  46. /*                                    */
  47. /*        Originally published (in Modula-2) in            */
  48. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  49. /*                                    */
  50. /*     AmigaDOS conversion copyright 1989 by Charlie Gibbs.        */
  51. /*                                    */
  52. /*------------------------------------------------------------------*/
  53.  
  54. #include <stdio.h>
  55. #include "a68kdef.h"
  56. #include "a68kglb.h"
  57.  
  58. char Sdata[MAXSREC];    /* S-record data */
  59. int  Sindex;        /* Index for Sdata */
  60. int  NumRExt, NumR32, NumR16, NumR8;
  61.  
  62. static char *errmsg[] =    {
  63.     "--- Unknown error code ---",
  64.     "Alignment error.",
  65.     "No such op-code.",
  66.     "Duplicate Symbol.",
  67.     "Undefined Symbol.",
  68.     "Addressing mode not allowed here.",
  69.     "Error in operand format.",
  70.     "Error in relative branch.",
  71.     "Address mode error.",
  72.     "Operand size error.",
  73.     "END statement is missing.",
  74.     "Value must be absolute.",
  75.     "Relocatability error.",
  76.     "INCLUDE file cannot be opened.",
  77.     "Illegal forward reference.",
  78.     "Not supported in S-format.",
  79.     "This instruction needs a label.",
  80.     "Pass 1 / Pass 2 phase error.",
  81.     "ENDM statement is missing.",
  82.     "ENDC statement is missing.",
  83.     "Unmatched ENDC statement.",
  84.     "Too much DC data.",
  85.     "Too many SECTIONs.",
  86.     "Duplicate macro definition.",
  87.     "More than one label on this line.",
  88.     "End of string is missing.",
  89.     "Short displacement can't be zero.",
  90.     ""};
  91.  
  92. /* Functions */
  93. extern int  LineParts(), Instructions(), ObjDir();
  94. extern int  GetInstModeSize(), GetMultReg(), CountNest();
  95. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  96. extern long GetValue(),    CalcValue();
  97. extern char *AddName(),    *GetField();
  98. extern struct SymTab *NextSym();
  99. extern struct SymTab **HashIt();
  100.  
  101. long AddrBndW(), AddrBndL();
  102.  
  103.  
  104.  
  105. long AddrBndW (v) register long    v;
  106. /* Advances "v" to the next word boundary */
  107. {
  108.     register int i;
  109.  
  110.     if (v & 1L)    {
  111.     AppendSdata (0L, 1);
  112.     v++;
  113.     }
  114.     return (v);
  115. }
  116.  
  117.  
  118.  
  119. long AddrBndL (v) register long    v;
  120. /* Advances "v" to the next long-word boundary */
  121. {
  122.     long templong;
  123.  
  124.     v =    AddrBndW (v);        /* Bump    to a word boundary first */
  125.     if (v & 2L)    {        /* If still not    aligned, */
  126.     templong = NOP;        /*  generate a NOP */
  127.     AppendSdata (templong, 2);
  128.     v += 2;
  129.     }
  130.     return (v);
  131. }
  132.  
  133.  
  134.  
  135. WriteListLine (f) struct fs *f;
  136. /* Writes one line to the Listing file,    including Object Code */
  137. {
  138.     register int i, j, printed;
  139.     long templong;
  140.     char macflag;
  141.     char tempstr[12];
  142.     int     dummy;
  143.  
  144.     if (!Pass2)
  145.     return;            /* Pass    2 only */
  146.     if (FwdShort && (ErrLim == 0)) {
  147.     DisplayLine (dummy);
  148.     printf ("A short branch can be used here.\n");
  149.     }
  150.     if (SuppList)
  151.     return;            /* Listing is suppresed    */
  152.     if (ErrLim == 0)
  153.     if ((Dir == Page) || (Dir == Space) || (Dir == Title)
  154.     || (Dir    == DoList) || (Dir == NoList) || (ListOff))
  155.         return;        /* Don't print unless they have errors */
  156.  
  157.     CheckPage (f, FALSE);    /* Print headings if necessary */
  158.  
  159.     if (PrntAddr) {
  160.     if ((Dir == Equ) || (Dir == Set))
  161.         LongPut (f,    ObjSrc,    3);    /* Equated value */
  162.     else
  163.         LongPut (f,    AddrCnt, 3);    /* Current location */
  164.     if (!KeepTabs)
  165.         xputs (f, "  ");
  166.     } else
  167.     if (!KeepTabs)
  168.         xputs (f, "        ");      /* Don't print location */
  169.     if (KeepTabs)
  170.     xputs (f, "\t");                /* Use tabs for spacing */
  171.     printed = 8;            /* We've printed 8 positions */
  172.     LongPut (f,    ObjOp, nO);        /* Generated code */
  173.     printed += nO * 2;
  174.     if (nS != 0) {
  175.     xputs (f, " ");
  176.     LongPut    (f, ObjSrc, nS);
  177.     printed    += nS *    2 + 1;
  178.     }
  179.     if (nD != 0) {
  180.     xputs (f, " ");
  181.     LongPut    (f, ObjDest, nD);
  182.     printed    += nD *    2 + 1;
  183.     }
  184.     if ((j = nX) > 0) {                /* String data */
  185.     if ((j * 2 + printed) >    ObjMAX)
  186.         j =    (ObjMAX    - printed) / 2;
  187.     for (i = 0; i <    j; i++)    {
  188.         templong = ObjString[i];
  189.         LongPut (f,    templong, 1);
  190.     }
  191.     printed    += j * 2;
  192.     }
  193.     while (printed < ObjMAX) {
  194.     if (KeepTabs) {
  195.         xputs (f, "\t");
  196.         printed += 8;
  197.         printed &= ~7;
  198.     } else {
  199.         xputs (f, " ");
  200.         printed++;
  201.     }
  202.     }
  203.     if ((InFNum    == 0) || (OuterMac == 0))
  204.     macflag    = ' ';                  /* Open code */
  205.     else if (InFNum > OuterMac)
  206.     macflag    = '+';                  /* Inner macro */
  207.     else if ((InFNum ==    OuterMac) && (Dir != MacCall))
  208.     macflag    = '+';                  /* Outermost macro */
  209.     else
  210.     macflag    = ' ';                  /* We're outside macros */
  211.  
  212.     sprintf (tempstr, "  %5d%c", LineCount, macflag);
  213.     xputs (f, tempstr);
  214.     xputs (f, Line);
  215.     xputs (f, "\n");
  216.  
  217.     if (FwdShort && (ErrLim == 0))
  218.     xputs (f, "A short branch can be used here.\n");
  219.  
  220.     for    (i = 0;    i < ErrLim; i++) {    /* Write error messages. */
  221.     CheckPage (f, FALSE);
  222.     xputs (f, errmsg[ErrCode[i]]);
  223.     printed    = strlen(errmsg[ErrCode[i]]);
  224.     while (printed < ObjMAX    + 8) {
  225.         if (KeepTabs) {
  226.         xputs (f, "\t");
  227.         printed    += 8;
  228.         printed    &= ~7;
  229.         } else {
  230.         xputs (f, " ");
  231.         printed++;
  232.         }
  233.     }
  234.     for (j = 0; j <    ErrPos[i]; j++)    {
  235.         if (Line[j]    == '\t') {
  236.         xputs (f, "\t");
  237.         printed    += 8;
  238.         printed    &= ~7;
  239.         } else {
  240.         xputs (f, " ");
  241.         printed++;
  242.         }
  243.     }
  244.     xputs (f, "^ ");                        /* Error flag */
  245.     if (i == 0) {
  246.         if (InF->UPtr == 0)
  247.         xputs (f, InF->NPtr);        /* Module name */
  248.         else
  249.         xputs (f, "(user macro)");      /* In a user macro */
  250.         sprintf (tempstr, " line %d", InF->Line);
  251.         xputs (f, tempstr);            /* Line    number */
  252.     }
  253.     xputs (f, "\n");
  254.     }
  255. }
  256.  
  257.  
  258.  
  259. WriteSymTab (f)    struct fs *f;
  260. /* Lists the symbol table in alphabetical order    */
  261. {
  262.     int     printhunk, i;
  263.     char *p;
  264.     char tempstr[24];
  265.     long templong;
  266.     register int j, k;
  267.     register struct SymTab **ss1, **ss2, *sym, **sortlim;
  268.     struct Ref *ref;
  269.  
  270.     if (NumSyms    == 0)
  271.     return;            /* The symbol table is empty - exit */
  272.  
  273. /* Build a sorted table    of pointers to symbol table entries */
  274.  
  275.     templong = NumSyms * sizeof    (struct    SymTab *);
  276.     SymSort = (struct SymTab **) malloc    ((unsigned) templong);
  277.     if (SymSort    == NULL) {
  278.     fprintf    (stderr, "Not enough memory for symbol table sort!\n");
  279.     return;
  280.     }
  281.     sortlim = SymSort +    NumSyms;
  282.     sym    = SymChunk = SymStart;
  283.     sym++;
  284.     SymChLim = (struct SymTab *) ((char    *) SymChunk + CHUNKSIZE);
  285.     ss1    = SymSort;
  286.     while (sym)    {
  287.     *ss1++ = sym;
  288.     sym = NextSym (sym);    /* Try for another symbol table    entry */
  289.     }
  290.     for    (i = NumSyms / 2; i > 0; i /= 2) {        /* Shell sort */
  291.     for (ss1 = SymSort + i;    ss1 < sortlim; ss1++) {    /*  (copied   */
  292.         for    (ss2=ss1-i; ss2    >= SymSort; ss2    -= i) {    /*  from K&R) */
  293.         if (strcmp ((*ss2)->Nam, (*(ss2+i))->Nam) <= 0)
  294.             break;
  295.         sym = *ss2;
  296.         *ss2 = *(ss2+i);
  297.         *(ss2+i) = sym;
  298.         }
  299.     }
  300.     }
  301.  
  302. /* The table is    now sorted - print the listing */
  303.  
  304.     LnCnt = LnMax;            /* Skip    to a new page. */
  305.     for    (i = 0,    ss1 = SymSort; i < NumSyms; i++) {
  306.     sym = *ss1++;
  307.     CheckPage (f, TRUE);
  308.  
  309.     p = sym->Nam;            /* Pointer to symbol */
  310.     if (sym->Flags & 8)
  311.         p++;            /* Skip    blank preceding    macro name */
  312.     else if    (sym->Flags & 0x10)
  313.         p += 6;            /* Skip    hunk sequence number */
  314.     sprintf    (tempstr, "%-11s ", p); /* Symbol or macro name */
  315.     xputs (f, tempstr);
  316.     if (strlen (p) > 11)        /* Long    symbol - go to new line    */
  317.         if (KeepTabs)
  318.         xputs (f, "\n\t    ");
  319.         else
  320.         xputs (f, "\n            ");
  321.  
  322.     printhunk = FALSE;        /* Assume no hunk no. to print */
  323.     if (sym->Defn == NODEF)
  324.         xputs (f, "  *** UNDEFINED *** ");
  325.     else if    (sym->Flags & 4)
  326.         xputs (f, "  -- SET Symbol --  ");
  327.     else if    (sym->Flags & 8) {
  328.         sprintf (tempstr, " +++ MACRO +++ %5d", sym->Defn);
  329.         xputs (f, tempstr);
  330.     } else if (sym->Flags &    0x10) {
  331.         j =    (sym->Hunk & 0x3FFF0000L) >> 16;
  332.         if (j == HunkCode)
  333.         xputs (f, "  CODE    ");
  334.         else if (j == HunkData)
  335.         xputs (f, "  DATA    ");
  336.         else
  337.         xputs (f, "  BSS     ");
  338.         printhunk =    TRUE;
  339.     } else if (sym->Flags &    0x20) {
  340.         sprintf (tempstr, "      %c%ld  ",
  341.         (sym->Val & 8L)    ? 'A' : 'D', sym->Val & 7L);
  342.         xputs (f, tempstr);
  343.         printhunk =    TRUE;
  344.     } else {
  345.         LongPut (f,    sym->Val, 4);        /* Value */
  346.         xputs (f, "  ");
  347.         printhunk =    TRUE;
  348.     }
  349.     if (printhunk) {
  350.         j =    sym->Hunk & 0x00007FFFL;    /* Hunk    number */
  351.         if (sym->Flags & 0x60)
  352.         xputs (f, " Reg");              /* Register or list */
  353.         else if (sym->Flags    & 1)
  354.         xputs (f, " Ext");              /* External */
  355.         else if (j == ABSHUNK)
  356.         xputs (f, " Abs");              /* Absolute */
  357.         else {
  358.         sprintf    (tempstr, "%4d", j);    /* Hunk number */
  359.         xputs (f, tempstr);
  360.         }
  361.         sprintf (tempstr," %5d",sym->Defn); /* Statement number */
  362.         xputs (f, tempstr);
  363.     }
  364.     if (XrefList) {
  365.         xputs (f, "  ");
  366.         if (sym->Ref1 == NULL)
  367.         xputs (f, " *** UNREFERENCED ***");
  368.         else {
  369.         ref = sym->Ref1;
  370.         j = k =    0;
  371.         while (1) {
  372.             if (ref->RefNum[j] == 0)
  373.             break;
  374.             if (k >= 9)    {
  375.             xputs (f, "\n");        /* New line */
  376.             if (KeepTabs)
  377.                 xputs (f, "\t\t\t\t  ");    /* 34 spaces */
  378.             else
  379.                 for    (k = 0;    k < 34;    k++)
  380.                 xputs (f, " ");
  381.             k = 0;
  382.             }
  383.             sprintf (tempstr, "%5d", ref->RefNum[j]);
  384.             xputs (f, tempstr);
  385.             j++;
  386.             k++;
  387.             if (j < MAXREF)
  388.             continue;        /* Get the next    slot */
  389.             if ((ref = ref->NextRef) ==    0)
  390.             break;            /* End of last entry */
  391.             j =    0;            /* Start the next entry    */
  392.         }
  393.         }
  394.     }
  395.     xputs (f, "\n");
  396.     }
  397.     free (SymSort);        /* Free    the sort work area */
  398.     SymSort = NULL;
  399. }
  400.  
  401.  
  402.  
  403. CheckPage (f, xhdr) struct fs *f; int xhdr;
  404. /* Checks if end of page reached yet --    if so, advances    to next    page. */
  405. {
  406.     register int printed;
  407.     char tempstr[12];
  408.  
  409.     LnCnt++;
  410.     if (LnCnt >= LnMax)    {
  411.     PgCnt++;
  412.     if (PgCnt > 1)
  413.         xputs (f, "\f");            /* Skip to new page */
  414.     xputs (f, TTLstring);        /* Title */
  415.     printed    = strlen (TTLstring);
  416.     while (printed < 56)
  417.         if (KeepTabs) {
  418.         xputs (f, "\t");
  419.         printed    += 8;
  420.         printed    &= ~7;
  421.         } else {
  422.         xputs (f, " ");
  423.         printed++;
  424.         }
  425.     xputs (f, SourceFN);        /* File    name */
  426.     if (KeepTabs)
  427.         xputs (f, "\t");
  428.     else
  429.         xputs (f, "        ");
  430.     sprintf(tempstr, "Page %d\n\n", PgCnt); /* Page number */
  431.     xputs (f, tempstr);
  432.     LnCnt =    2;
  433.     if (xhdr) {
  434.         xputs (f, "Symbol       Value    Hunk  Line");
  435.         if (XrefList)
  436.         xputs (f, "   References");     /* Cross-reference */
  437.         xputs (f, "\n\n");
  438.         LnCnt += 2;
  439.     }
  440.     }
  441. }
  442.  
  443.  
  444.  
  445. StartSrec (f, idntname)    struct fs *f; char *idntname;
  446. /* Writes object header    record */
  447. {
  448.     register long CheckSum, templong;
  449.     register char *s;
  450.  
  451.     if (SFormat) {
  452.     xputs (f, "S0");
  453.     templong = strlen (idntname) + 3; /* extra for addr. & checksum    */
  454.     LongPut    (f, templong, 1);
  455.     CheckSum = templong;
  456.  
  457.     xputs (f, "0000");  /* Address is 4 digits, all zero, for S0 */
  458.  
  459.     s = idntname;
  460.     while (*s) {
  461.         templong = toupper (*s++);
  462.         LongPut (f,    templong, 1);
  463.         CheckSum +=    templong;
  464.     }
  465.     CheckSum = ~CheckSum;        /* Complement checksum */
  466.     LongPut    (f, CheckSum, 1);
  467.     xputs (f, "\n");
  468.     } else {
  469.     templong = HunkUnit;
  470.     xputl (f, templong);
  471.     DumpName (f, idntname, 0L);
  472.     }
  473.     StartAddr =    TempAddr = Sindex = 0;
  474.     NumRExt = NumR32 = NumR16 =    NumR8 =    0;
  475. }
  476.  
  477.  
  478.  
  479. WriteSrecLine (f) struct fs *f;
  480. /* Transfers object code components to output buffer. */
  481. /* Moves long words or portions    thereof. */
  482. {
  483.     register int i;
  484.     register long templong;
  485.  
  486.     if (HunkType == HunkBSS)
  487.     return;                /* No code in BSS hunk */
  488.  
  489.     if (nO + nS    + nD + nX) {        /* If we have object code */
  490.     AppendSdata (ObjOp, nO);    /* Opcode */
  491.     AppendSdata (ObjSrc, nS);    /* Source */
  492.     AppendSdata (ObjDest, nD);    /* Destination */
  493.     for (i = 0; i <    nX; i++) {    /* String data */
  494.         templong = ObjString[i];
  495.         AppendSdata    (templong, 1);
  496.     }
  497.     }
  498. }
  499.  
  500.  
  501.  
  502. AppendSdata (Data, n) register long Data; int n;
  503. /* If we are producing S-format    records:
  504.      Transfers "n" low-order bytes from "Data" to the output buffer.
  505.      If    the buffer becomes full, DumpSdata will    be called to flush it.
  506.      S-records will also be broken on 16-byte boundaries.
  507.    If we are producing AmigaDOS    format,    data will be written
  508.      directly to Srec -    we'll go back and fill in the hunk length
  509.      at    the end    of the hunk.  DumpSdata    will never be called from here.    */
  510. {
  511.     register int  i;
  512.     register char byte;
  513.     int     dummy;
  514.  
  515.     if (!Pass2)
  516.     return;            /* Pass    2 only */
  517.     if (HunkType == HunkBSS)
  518.     return;            /* No data in BSS hunks! */
  519.  
  520.     if (HunkType == HunkNone) {        /* We're not in a hunk yet - */
  521.     DoSection ("", 0, "", 0, "", 0);        /* start a code hunk */
  522.     MakeHunk = TRUE;
  523.     }
  524.  
  525.     if (OrgFlag) {        /* If we've had an ORG directive */
  526.     FixOrg (dummy);        /*  do necessary adjustments     */
  527.     OrgFlag    = FALSE;    /*  to the object code file.     */
  528.     }
  529.  
  530.     Data <<= (4    - n) * 8;    /* Left-justify    data */
  531.  
  532.     for    (i = 0;    i < n; i++) {
  533.     byte = (char) (Data >> ((3 - i)    * 8));
  534.     TempAddr++;
  535.     if (!SFormat) {
  536.         xputc (byte, &Srec);
  537.     } else {
  538.         Sdata[Sindex++] = byte;
  539.         if (((TempAddr & 0x0F) == 0) || (Sindex >= MAXSREC))
  540.         DumpSdata (&Srec);    /* Break S-record */
  541.     }
  542.     }
  543. }
  544.  
  545.  
  546.  
  547. FixOrg (dummy) int dummy;
  548. /* Makes necessary adjustments to the object code file if an
  549.     ORG    directive has been processed.  This routine is called
  550.     exclusively    by AppendSdata and must    only be    called once for
  551.     each ORG encountered, when writing the next    object code (if    any). */
  552. {
  553.     register long templong;
  554.     register int  i;
  555.  
  556.     if (SFormat    && (AddrCnt != TempAddr)) {    /* ORG in S-format -    */
  557.     DumpSdata (&Srec);            /*  dump current record    */
  558.     StartAddr = TempAddr = AddrCnt;        /*  and    start afresh.    */
  559.     }
  560.     if (AddrCnt    < TempAddr) {        /* AmigaDOS backward ORG */
  561.     if (TempAddr > OrgHigh)    {
  562.         LenPtr = NULL;
  563.         OrgHigh = TempAddr;    /* Save    high address for return    */
  564.         if (Srec.Ptr > Srec.Buf)    /* Flush the buffer */
  565.         write (Srec.fd,    Srec.Buf, Srec.Ptr - Srec.Buf);
  566.         OrgSeek = lseek (Srec.fd, 0L, 1);    /* Remember position */
  567.         lseek (Srec.fd,(AddrCnt & ~3L)-TempAddr,1);    /* New position    */
  568.         if (AddrCnt    & 3L) {        /* If ORG isn't to long-word   */
  569.         read (Srec.fd, Srec.Buf, AddrCnt & 3L);    /*  move ahead */
  570.         lseek (Srec.fd,    -(AddrCnt & 3L), 1);    /*  to keep    */
  571.         }                        /*  the    buffer */
  572.         Srec.Ptr = Srec.Buf    + (AddrCnt & 3L);    /*  aligned.   */
  573.     }
  574.     StartAddr = TempAddr = AddrCnt;
  575.  
  576.     } else if (AddrCnt > TempAddr) {    /* AmigaDOS forward ORG    */
  577.     if (OrgHigh > TempAddr)    {    /* Previous backward ORG */
  578.         if (AddrCnt    < OrgHigh)
  579.         templong = AddrCnt;    /* Within previous range */
  580.         else
  581.         templong = OrgHigh;    /* Beyond previous range */
  582.         i =    (int) (templong    & 3L);    /* Alignment factor */
  583.         templong -=    TempAddr;    /* Number of bytes to skip */
  584.         LenPtr = NULL;
  585.         if (Srec.Ptr > Srec.Buf)    /* Flush the buffer */
  586.         write (Srec.fd,    Srec.Buf, Srec.Ptr - Srec.Buf);
  587.         lseek (Srec.fd,templong-(long)i,1);    /* Skip    written    data */
  588.         if (i) {        /* If skip isn't to long-word, */
  589.         read(Srec.fd,Srec.Buf,(long)i);    /*  move ahead */
  590.         lseek(Srec.fd, -((long)    i), 1);    /*  to keep    */
  591.         }                    /*  the    buffer */
  592.         Srec.Ptr = Srec.Buf    + (long) i;    /*  aligned.   */
  593.         TempAddr +=    templong;
  594.         StartAddr =    TempAddr;
  595.     }
  596.     while (TempAddr    < AddrCnt) {    /* Extend with binary zeros */
  597.         xputc (0, &Srec);
  598.         TempAddr++;
  599.     }
  600.     }
  601. }
  602.  
  603.  
  604.  
  605. DumpSdata (f) register struct fs *f;
  606. /* Writes an object code record    */
  607. {
  608.     register long CheckSum, templong;
  609.     register char *s;
  610.     register int  i;
  611.  
  612.     if (!SFormat) {
  613.     if (AddrCnt < OrgHigh) {    /* If we did a backwards ORG */
  614.         LenPtr = NULL;        /*  we have to fix things up */
  615.         if (f->Ptr > f->Buf)    /* Flush the buffer */
  616.         write (f->fd, f->Buf, f->Ptr - f->Buf);
  617.         lseek(f->fd,OrgSeek&~3L,0);    /* Back    to high    position */
  618.         if (OrgSeek    & 3L) {        /* If ORG isn't to long-word,  */
  619.         read (f->fd, f->Buf, OrgSeek & 3L);    /*  move ahead */
  620.         lseek (f->fd, -(OrgSeek    & 3L), 1);    /*  to keep    */
  621.         }                        /*  the    buffer */
  622.         f->Ptr = f->Buf + (OrgSeek & 3L);        /*  aligned.   */
  623.         AddrCnt = StartAddr    = TempAddr = OrgHigh;
  624.     }
  625.     AddrCnt    = AddrBndL (AddrCnt);    /* Finish the last long    word */
  626.     templong = ((AddrCnt - SectStart) >> 2)    | HunkFlags;
  627.     if ((s = LenPtr) == NULL) {
  628.         if (f->Ptr > f->Buf)        /* Flush the buffer */
  629.         write (f->fd, f->Buf, f->Ptr - f->Buf);
  630.         CheckSum = lseek (f->fd, 0L, 1);    /* Remember position */
  631.         lseek (f->fd, LenPos, 0);        /* Put hunk length here    */
  632.         s =    f->Buf;
  633.     }
  634.     *s++ = (char) (templong    >> 24);
  635.     *s++ = (char) (templong    >> 16);
  636.     *s++ = (char) (templong    >> 8);
  637.     *s++ = (char) templong;
  638.     if (LenPtr == NULL) {
  639.         write (f->fd, f->Buf, 4);
  640.         lseek (f->fd, CheckSum, 0);    /* Back    to where we were */
  641.         f->Ptr = f->Buf;
  642.     }
  643.     DumpRel    (f);        /* Write relocation information    */
  644.     templong = HunkEnd;
  645.     xputl (f, templong);    /* End of the hunk */
  646.     TempAddr = AddrCnt;
  647.     return;
  648.     }
  649.  
  650.     if (Sindex == 0)
  651.      return;        /* There's nothing to dump */
  652.  
  653.     xputs (f, "S2");
  654.     templong = Sindex +    4;    /* Record length */
  655.     LongPut (f,    templong, 1);
  656.     CheckSum = templong;    /* Initialize CheckSum */
  657.  
  658.     LongPut (f,    StartAddr, 3);    /* Address */
  659.     CheckSum +=    (StartAddr >> 16) & 0x00FFL;
  660.     CheckSum +=    (StartAddr >> 8) & 0x00FFL;
  661.     CheckSum +=    StartAddr & 0x00FFL;
  662.  
  663.     for    (i = 0;    i < Sindex; i++) {
  664.     templong = Sdata[i];
  665.     LongPut    (f, templong, 1);    /* Object code */
  666.     CheckSum += templong;
  667.     }
  668.     CheckSum = ~CheckSum;    /* Complement checksum */
  669.     LongPut (f,    CheckSum, 1);
  670.     xputs (f, "\n");
  671.  
  672.     StartAddr += Sindex;
  673.     TempAddr = StartAddr;
  674.     Sindex = 0;
  675. }
  676.  
  677.  
  678.  
  679. PutRel (addr, hunk, size) long addr, hunk; int size;
  680. /* Build a relocation entry if necessary */
  681. {
  682.     register struct RelTab *rel;
  683.  
  684.     if (!Pass2)
  685.     return;                /* Pass    2 only */
  686.     if (SFormat)
  687.     return;                /* Not for S-format! */
  688.     if (hunk ==    ABSHUNK)
  689.     return;                /* Absolute */
  690.     if (HunkType == HunkBSS)
  691.     return;                /* Not for BSS hunks! */
  692.  
  693.     rel    = RelLim;            /* Pointer to new entry    */
  694.     RelLim++;                /* Bump    limit pointer */
  695.     if (((char *) RelLim - (char *) RelCurr) > CHUNKSIZE) {
  696.     rel = (struct RelTab *)    malloc ((unsigned) CHUNKSIZE);
  697.     if (rel    == NULL)
  698.         quit_cleanup ("Out of memory!\n");
  699.     RelCurr->Link =    rel;        /* Link    from previous chunk */
  700.     RelCurr    = rel;            /* Make    the new    chunk current */
  701.     RelCurr->Link =    NULL;        /* Clear forward pointer */
  702.     rel++;                /* Skip    over pointer entry */
  703.     RelLim = rel;            /* New table limit */
  704.     RelLim++;            /* Bump    it */
  705.     }
  706.     if (RelLast    != NULL)
  707.     RelLast->Link =    rel;        /* Link    from previous entry */
  708.     rel->Link =    NULL;            /* End of the chain (so    far) */
  709.     rel->Offset    = addr;            /* Offset */
  710.     rel->Hunk =    hunk;            /* Hunk    number */
  711.     rel->Size =    size;            /* Size    */
  712.     RelLast = rel;            /* Pointer to last entry in chain */
  713.  
  714.     if (hunk < 0)            /* Count entries by type */
  715.     NumRExt++;
  716.     else if (size == Long)
  717.     NumR32++;
  718.     else if (size == Word)
  719.     NumR16++;
  720.     else
  721.     NumR8++;
  722. }
  723.  
  724.  
  725.  
  726. DumpRel    (f) struct fs *f;
  727. /* Dump    relocation information to the object file. */
  728. {
  729.     register struct SymTab *sym;
  730.     register struct RelTab *rel, *rel2;
  731.     int     i, j, size, num, donexhdr, secthlin;
  732.     long currhunk, nexthunk, templong;
  733.     char *p;
  734.  
  735.     secthlin = LineCount;        /* Current section ends    here */
  736.     if ((Dir ==    Section)        /*   unless we're starting   */
  737.     || (Dir == CSeg)            /*    a new section.         */
  738.     || (Dir == DSeg)
  739.     || (Dir == BSS))
  740.     secthlin--;            /* Then    it ends    at previous line */
  741.  
  742.     if (SFormat)
  743.     return;                /* S-format is absolute! */
  744.  
  745.     while (1) {
  746.     if ((num = NumR32) != 0) {
  747.         size = Long;        /* Do 32-bit fields */
  748.         templong = HunkR32;
  749.         NumR32 = 0;            /* ...but only once */
  750.     } else if ((num    = NumR16) != 0)    {
  751.         size = Word;        /* Then    do 16-bit fields */
  752.         templong = HunkR16;
  753.         NumR16 = 0;
  754.     } else if ((num    = NumR8) != 0) {
  755.         size = Byte;        /* Finally do 8-bit fields */
  756.         templong = HunkR8;
  757.         NumR8 = 0;
  758.     } else
  759.         break;            /* We're all done */
  760.  
  761.     xputl (f, templong);        /* Record type */
  762.  
  763.     currhunk = 32767;
  764.     num = 0;
  765.     if (rel    = RelStart)    /* If we have anything,    */
  766.         rel++;        /*  skip over the first    chunk's link. */
  767.     while (rel) {
  768.         if ((rel->Size == size) && (rel->Hunk >= 0)) {
  769.         if (rel->Hunk <    currhunk) {
  770.             currhunk = rel->Hunk;    /* Lowest hunk number */
  771.             num    = 1;            /* Reset counter */
  772.         } else if (rel->Hunk ==    currhunk) {
  773.             num++;            /* Count entries */
  774.         }
  775.         }
  776.         rel    = rel->Link;
  777.     }
  778.     while (num > 0)    {    /* Repeat for all hunk references */
  779.         templong = num;
  780.         xputl (f, templong);    /* Number of entries */
  781.         xputl (f, currhunk);    /* Hunk    number */
  782.         nexthunk = 32767;
  783.         num    = 0;            /* Count for next hunk */
  784.         if (rel = RelStart)
  785.         rel++;
  786.         while (rel)    {
  787.         if ((rel->Size == size)    && (rel->Hunk >= 0)) {
  788.             if (rel->Hunk < currhunk) {
  789.             rel = rel->Link;    /* Already wrote it */
  790.             continue;
  791.             } else if (rel->Hunk == currhunk) {
  792.             xputl (f, rel->Offset -    SectStart);
  793.             } else if (rel->Hunk < nexthunk) {
  794.             nexthunk = rel->Hunk;    /* Next    hunk number */
  795.             num = 1;        /* Reset counter */
  796.             } else if (rel->Hunk == nexthunk) {
  797.             num++;            /* Count entries */
  798.             }
  799.         }
  800.         rel = rel->Link;
  801.         }
  802.         currhunk = nexthunk;    /* Get ready for next hunk */
  803.     }
  804.     xputl (f, 0L);        /* End of relocation information */
  805.     }
  806.  
  807.     donexhdr = FALSE;        /* Haven't written hunk_ext yet */
  808.  
  809.     sym    = SymChunk = SymStart;
  810.     sym++;
  811.     SymChLim = (struct SymTab *) ((char    *) SymChunk + CHUNKSIZE);
  812.     while (sym)    {
  813.     if (sym->Flags & 2) {        /* Scan    for XDEF symbols */
  814.         j =    sym->Defn;    /* Defined in current section? */
  815.         if ((j >= SectLine)    && (j <= secthlin)) {
  816.         if (!donexhdr) {
  817.             templong = HunkExt;    /* Haven't done header yet */
  818.             xputl (f, templong);
  819.             donexhdr = TRUE;
  820.         }
  821.         if ((sym->Hunk & 0x0000FFFFL) == ABSHUNK)
  822.             templong = 0x02000000;
  823.         else
  824.             templong = 0x01000000;        /* Flags */
  825.         DumpName (f, sym->Nam, templong);    /* Symbol */
  826.         xputl (f, sym->Val - SectStart);    /* Offset */
  827.         }
  828.     }
  829.     sym = NextSym (sym);
  830.     }
  831.  
  832.     if (NumRExt    != 0) {            /* External references (XREF) */
  833.     if (!donexhdr) {
  834.         templong = HunkExt;        /* Haven't done header yet */
  835.         xputl (f, templong);
  836.         donexhdr = TRUE;
  837.     }
  838.     if (rel    = RelStart)
  839.         rel++;
  840.     while (rel) {
  841.         if (rel->Hunk < 0) {
  842.         p = (char *) ~(rel->Hunk);
  843.         size = rel->Size;
  844.         if (size == Long)
  845.             templong = 0x81000000L;    /* ext_ref32 */
  846.         else if    (size == Word)
  847.             templong = 0x83000000L;    /* ext_ref16 */
  848.         else
  849.             templong = 0x84000000L;    /* ext_ref8 */
  850.         DumpName (f, p,    templong);    /* Flags and symbol */
  851.         templong = 1;
  852.         rel2 = rel->Link;
  853.         while (rel2) {
  854.             if ((rel2->Hunk == rel->Hunk) && (rel2->Size == size))
  855.             templong++;        /* Number of times */
  856.             rel2 = rel2->Link;        /*  symbol occurs  */
  857.         }
  858.         xputl (f, templong);
  859.         rel2 = rel;            /* Now go back and  */
  860.         while (rel2) {            /*  write them out. */
  861.             if ((rel2->Hunk==rel->Hunk)    && (rel2->Size==size)) {
  862.             xputl(f, rel2->Offset -    SectStart); /* Offset */
  863.             if (rel2 != rel)    /* Kill    hunk so    we    */
  864.                 rel2->Hunk = 0;    /*  don't do it again */
  865.             }                /*  (we're done with  */
  866.             rel2 = rel2->Link;        /*  the    table anyway) */
  867.         }
  868.         }
  869.         rel    = rel->Link;
  870.     }
  871.     NumRExt    = 0;
  872.     }
  873.     if (donexhdr)
  874.     xputl (f, 0L);            /* End of external information */
  875.  
  876.     if (DumpSym) {            /* Dump    the symbol table */
  877.     donexhdr = FALSE;
  878.     sym = SymChunk = SymStart;
  879.     sym++;
  880.     SymChLim = (struct SymTab *) ((char *) SymChunk    + CHUNKSIZE);
  881.     while (sym) {
  882.         if ((sym->Hunk & 0x0000FFFFL) == CurrHunk) {
  883.         j = sym->Flags & 0x7F;        /* Ignore PUBLIC flag */
  884.         if ((j == 0) ||    (j == 2)) {    /* Defined, may    be XDEF    */
  885.             if ((sym->Defn >= SectLine)    && (sym->Defn <= secthlin)) {
  886.             if (!donexhdr) {    /* In current SECTION */
  887.                 templong = HunkSym;
  888.                 xputl (f, templong);    /* Write header    */
  889.                 donexhdr = TRUE;        /* if necessary    */
  890.             }
  891.             DumpName (f, sym->Nam, 0L);    /* Symbol */
  892.             xputl(f, sym->Val - SectStart);    /* Offset */
  893.             }
  894.         }
  895.         }
  896.         sym    = NextSym (sym);
  897.     }
  898.     if (donexhdr)
  899.         xputl (f, 0L);        /* End of symbol table dump */
  900.     }
  901.  
  902.     rel    = RelStart->Link;
  903.     while (rel != NULL)    {
  904.     rel2 = rel;
  905.     rel = rel2->Link;
  906.     free (rel2);            /* Free    all but    the first chunk    */
  907.     }
  908.     RelCurr = RelStart;            /* The first chunk is current */
  909.     RelCurr->Link = NULL;        /* Unlink additional chunks */
  910.     RelLast = NULL;            /* There are no    entries    left */
  911.     RelLim = RelStart;
  912.     RelLim++;                /* First unused    space */
  913. }
  914.  
  915.  
  916.  
  917. EndSdata (f, addr) struct fs *f; long addr;
  918. /* Write end record to object file */
  919. {
  920.     register long checksum, templong;
  921.  
  922.     if (SFormat) {
  923.     DumpSdata (f);            /* Write any remaining data */
  924.     xputs (f, "S804");              /* Record header */
  925.     checksum = 4;
  926.     LongPut    (f, addr, 3);        /* Transfer address */
  927.     checksum += (addr >> 16) & 0x00FFL;
  928.     checksum += (addr >> 8)    & 0x00FFL;
  929.     checksum += addr & 0x00FFL;
  930.     checksum = ~checksum;
  931.     LongPut    (f, checksum, 1);    /* Checksum */
  932.     xputs (f, "\n");
  933.     } else {
  934.     if (HunkType !=    HunkNone) {
  935.         DumpSdata (f);        /* Last    hunk's data */
  936.     }
  937.     }
  938. }
  939.  
  940.  
  941.  
  942. DumpName (f, name, flags) struct fs *f;    char *name; long flags;
  943. /* Writes a name preceded by a long word containing the
  944.     length of the name in long words.  The length word has
  945.     the    contents of "flags" ORed into it.  The name is padded
  946.     with binary    zeros to the next long word boundary. */
  947. {
  948.     register int  i;
  949.     register long templong;
  950.  
  951.     i =    strlen (name);
  952.     templong = (i + 3) >> 2;    /* Length of name (long    words) */
  953.     templong |=    flags;        /* Add flag bits */
  954.     xputl (f, templong);    /* Write length    and flags */
  955.     xputs (f, name);        /* Write the name itself */
  956.     while (i & 3) {
  957.     xputc ('\0', f);        /* Pad the last word */
  958.     i++;
  959.     }
  960. }
  961.  
  962.  
  963.  
  964. LongPut    (f, data, length) struct fs *f;    long data; int length;
  965. /* Writes to file "f" the hexadecimal interpretation of
  966.     the    bytes in "data".  The number of bytes written
  967.     (two hex digits per    byte) is given in "length" -
  968.     if less than 4, only low-order bytes are written. */
  969. {
  970.     register int i, j;
  971.     register char *t;
  972.     char xstr[9];
  973.  
  974.     t =    xstr;
  975.     for    (i = length * 8    - 4; i >= 0; i -= 4) {
  976.     j = (int) ((data >> i) & 0x0FL);
  977.     *t++ = (char) ((j > 9) ? (j - 10 + 'A') : (j + '0'));
  978.     }
  979.     *t = '\0';
  980.     xputs (f, xstr);
  981. }
  982.  
  983.  
  984.  
  985. xopen (name, f,    desc) char *name; struct fs *f;    char *desc;
  986. /* Opens the output file whose name is in "name",
  987.     setting up the file    structure pointed to by    "f".
  988.     This routine first allocates a file    buffer -
  989.     if unsuccessful, it    calls quit_cleanup.
  990.     Otherwise, it opens    the file - if unsuccessful,
  991.     displays an    error message using "desc" and returns TRUE.
  992.     If the file    is successfully    opened,    this routine returns FALSE. */
  993. {
  994.     if ((f->Buf    = (char    *) malloc (BUFFSIZE)) == NULL)
  995.     quit_cleanup ("Out of memory!\n");
  996.     if ((f->fd = creat (name, 1)) == -1) {
  997.     fprintf    (stderr, "Unable to open %s file.\n", desc);
  998.     f->fd =    NULL;
  999.     return (TRUE);
  1000.     }
  1001.     f->Ptr = f->Buf;
  1002.     f->Lim = f->Buf + BUFFSIZE;
  1003.     return (FALSE);
  1004. }
  1005.  
  1006.  
  1007.  
  1008. xputs (f, s) struct fs *f; register char *s;
  1009. /* Writes the string pointed to    by "s"
  1010.     to the output file whose structure is pointed to by    "f". */
  1011. {
  1012.     register char *t, *l;
  1013.  
  1014.     t =    f->Ptr;        /* Current position (use registers for speed) */
  1015.     l =    f->Lim;        /* End of buffer */
  1016.  
  1017.     while (*s) {
  1018.     *t++ = *s++;
  1019.     if (t >= l) {
  1020.         write (f->fd, f->Buf, t - f->Buf);    /* Flush the buffer */
  1021.         if (f == &Srec)
  1022.         LenPtr = NULL;    /* Hunk    length is no longer in buffer */
  1023.         t =    f->Buf;                /* Reset pointer */
  1024.     }
  1025.     }
  1026.     f->Ptr = t;                    /* Update pointer */
  1027. }
  1028.  
  1029.  
  1030.  
  1031. xputl (f, data)    register struct    fs *f; register    long data;
  1032. /* Writes to file "f" the contents of the long word in "data". */
  1033. {
  1034.     xputc ((char) (data    >> 24),    f);
  1035.     xputc ((char) (data    >> 16),    f);
  1036.     xputc ((char) (data    >> 8), f);
  1037.     xputc ((char) data,    f);
  1038. }
  1039.  
  1040.  
  1041.  
  1042. xputc (byte, f)    char byte; register struct fs *f;
  1043. /* Writes the byte contained in    "byte" to file "f". */
  1044. {
  1045.     register char *t;
  1046.  
  1047.     t =    f->Ptr;        /* Current position (use register for speed) */
  1048.  
  1049.     *t++ = byte;
  1050.     if (t >= f->Lim) {
  1051.     write (f->fd, f->Buf, t    - f->Buf);    /* Flush the buffer */
  1052.     if (f == &Srec)
  1053.         LenPtr = NULL;    /* Hunk    length is no longer in buffer */
  1054.     t = f->Buf;                /* Reset pointer */
  1055.     }
  1056.     f->Ptr = t;                    /* Update pointer */
  1057. }
  1058.  
  1059.  
  1060.  
  1061. xclose (f) struct fs *f;
  1062. /* Closes the output file whose    structure is pointed to    by "f".
  1063.     The    buffer is flushed if necessary,    then freed.        */
  1064. {
  1065.     if (f->Ptr > f->Buf)
  1066.     write (f->fd, f->Buf, f->Ptr - f->Buf);    /* Flush the buffer */
  1067.     close (f->fd);                /* Close the file */
  1068.     f->fd = NULL;
  1069.     free (f->Buf);                /* Free    the buffer */
  1070.     f->Buf = NULL;
  1071. }
  1072.  
  1073.  
  1074.  
  1075. Error (pos, errornum) int pos, errornum;
  1076. /* Displays error message #errornum.  If this is the first error for
  1077.     the    current    line, the line itself is displayed, preceded by    a
  1078.     message giving the current position    in the current module.
  1079.     If the line    is in a    macro or include file, the position in
  1080.     each nested    module is given, working out to    the source file.
  1081.     A flag is placed under the column indicated    by "pos".       */
  1082. {
  1083.     register int i;
  1084.     int    dummy;
  1085.  
  1086.     if (!Pass2 && (errornum != NoIncl))    {
  1087.     if (IncStart !=    0) {            /* Don't skip this     */
  1088.         IncStart = 0;            /*  INCLUDE file in    */
  1089.         if (SkipLim->Set1 != NULL) {    /*  pass 2 - we    must   */
  1090.         SetFixLim = SkipLim->Set1;    /*  re-read it to      */
  1091.         SetFixLim++;            /*  report its errors. */
  1092.         }
  1093.     }
  1094.     return;                /* Report during pass 2    only */
  1095.     }
  1096.     if (ErrLim < ERRMAX) {        /* Save    error data */
  1097.     ErrCode[ErrLim]    = errornum;
  1098.     ErrPos[ErrLim] = pos;
  1099.     ErrLim++;
  1100.     }
  1101.     if (ErrLim == 1)        /* If first error for this line           */
  1102.     DisplayLine (dummy);    /*  display the    line and its number(s) */
  1103.     printf ("\t");
  1104.     for    (i = 0;    i < pos; i++)
  1105.     if (Line[i] == '\t')
  1106.         printf ("\t");
  1107.     else
  1108.         printf(" ");                /* Space over to error column */
  1109.     printf ("^ %s\n",errmsg[errornum]); /* Error flag and message */
  1110.     ErrorCount++;            /* Count errors    */
  1111. }
  1112.  
  1113.  
  1114.  
  1115. DisplayLine (dummy) int    dummy;
  1116. /* Displays the    current    line and its position
  1117.     in all current files - used    by Error, etc. */
  1118. {
  1119.     register struct InFCtl *inf;
  1120.     register int i;
  1121.  
  1122.     printf ("\n");
  1123.     for    (i = InFNum, inf = InF;    i >= 0;    i--, inf++) {    /* Nested? */
  1124.     if (inf->UPtr == 0)
  1125.         printf ("%s", inf->NPtr);           /* Module name */
  1126.     else
  1127.         printf ("(user macro)");            /* In a user macro */
  1128.     printf (" line %d\n", inf->Line);       /* Line number in module */
  1129.     }
  1130.     printf ("%5d   %s\n", LineCount, Line);     /* The line itself */
  1131. }
  1132. SHAR_EOF
  1133. cat << \SHAR_EOF > History.log
  1134.        A 6 8 K      M A I    N T E N    A N C E       H I S T O R Y
  1135.  
  1136.  
  1137. Version    2.42 (Charlie Gibbs, January 10, 1989)
  1138.  
  1139.     The following bugs in version 2.41 have    been corrected:
  1140.  
  1141.           -    Small code/data    conversion was sometimes taking    place
  1142.         when no    NEAR directive was active.  (Jeff Lydiatt)
  1143.  
  1144.  
  1145. Version    2.41 (Charlie Gibbs, January 6,    1989)
  1146.  
  1147.     The following bugs in version 2.4 have been corrected:
  1148.  
  1149.           -    The second operand of LINK instructions    was
  1150.         being erroneously flagged.
  1151.  
  1152.           -    If a macro was used before it was defined, it
  1153.         was being expanded during pass 2 but not during
  1154.         pass 1,    causing    severe phase errors.  Attempts
  1155.         to use a macro before it is defined will now
  1156.         be flagged as invalid opcodes.    (Colin Fox)
  1157.  
  1158.  
  1159. Version    2.4 (Charlie Gibbs, January 4, 1989)
  1160.  
  1161.     The following bugs in version 2.31 have    been corrected:
  1162.  
  1163.           -    If comments immediately    followed the operands of
  1164.         a DC statement with no intervening white space,
  1165.         A68k would hang.  (Ulf Nordquist)
  1166.  
  1167.           -    In the following command:
  1168.             a68k -w    15000 myprog.asm
  1169.         the space between the -w and 15000 would cause A68k
  1170.         to look    for a source file called "15000", and to think
  1171.         that the object    file is    to be called "myprog.asm".
  1172.         When it    can't find "15000" it would display an error
  1173.         message    and scratch "myprog.asm".  (Jeff Lydiatt)
  1174.  
  1175.           -    If an INCLUDE file that    is skipped on pass 2 contains
  1176.         a macro    calls, subsequent uses of \@ (macro sequence
  1177.         number are subsequently    flagged.  The macro counter
  1178.         must be    bumped along with the line number when
  1179.         skipping an INCLUDE.  (Colin Fox, Harvey Taylor)
  1180.  
  1181.     The following enhancements have    been added:
  1182.  
  1183.           -    ORG and    RORG are now fully implemented.
  1184.  
  1185.           -    The SET    symbols    A68k, a68K, and    a68k are defined in the
  1186.         same way as A68K, making it effectively    case-insensitive.
  1187.         (Colin Fox)
  1188.  
  1189.           -    MOVEM and REG now accept equated register names    (EQUR)
  1190.         in register lists.  (Bruce Dawson)
  1191.  
  1192.           -    INCLUDE    files will now be skipped on pass 2 even when
  1193.         a listing file is requested, if    the listing has    been
  1194.         turned off by a    NOLIST directive before    the INCLUDE,
  1195.         and is not turned on until after the end of the
  1196.         INCLUDE    file has been reached.    (Colin Fox)
  1197.  
  1198.           -    A new switch (-f) causes forward branches (Bcc,    BRA, BSR)
  1199.         that could be coded as short branches (Bcc.S etc.) to be
  1200.         flagged.  This flag is not considered to be an error.
  1201.  
  1202.           -    A limited small    code / small data model    has been provided.
  1203.         It is activated    by a NEAR directive in the code, and is
  1204.         de-activated by    a FAR directive.  External variables must
  1205.         be declared at the beginning of    the program, which must
  1206.         consist    of only    two sections (CODE and DATA or BSS).
  1207.         All forward data references are    assumed    to be PC-relative
  1208.         if in the CODE section,    A4-relative if in the DATA/BSS
  1209.         section, and absolute word if absolute values.    Any
  1210.         forward    references which cannot    be resolved to one of
  1211.         these three in pass 2 will be flagged as errors, as will
  1212.         any attempt to define more than    two sections.  A4 is
  1213.         assumed    to point to the    start of the DATA/BSS section
  1214.         plus 32768 bytes, and must be loaded by    a MOVE.L
  1215.         instruction using immediate mode unless    this instruction
  1216.         is not enclosed    within NEAR and    FAR directives.
  1217.  
  1218.           -    Miscellaneous optimizations, for speed,    including:
  1219.         Most of    the object code    generator in pass 1 is bypassed.
  1220.         If GetValue gets a single term it takes    a short    cut.
  1221.         IsOperator now uses a table look-up.
  1222.         Instructions now only searches that portion of the
  1223.         opcode table whose opcodes start with the same letter
  1224.         as the OpCode being searched for.
  1225.  
  1226.  
  1227. Version    2.31 (Charlie Gibbs, November 30, 1988)
  1228.  
  1229.     The following bugs in version 2.3 have been corrected:
  1230.  
  1231.           -    Even though a macro definition was being skipped
  1232.         by IFxx/ENDC, its ENDM directive was still being
  1233.         detected, causing spurious diagnostics.     (Harvey Taylor)
  1234.  
  1235.           -    NOP was    not being recognized.  When moving all
  1236.         directives into    the opcode table, NOL and NOLIST
  1237.         were placed after NOP, rather than before.  (Colin Fox)
  1238.  
  1239.           -    Symbols    defined    in the current module and declared
  1240.         as PUBLIC were not being written to the    object code
  1241.         file when -d was specified.  (Colin Fox)
  1242.  
  1243.           -    Conversion of 0(An) to (An) (implemented in version
  1244.         1.2) was causing errors    in the MOVEP instruction,
  1245.         which requires a displacement even if it is zero.
  1246.         This conversion    is now disabled    for MOVEP instructions.
  1247.  
  1248.           -    User macros containing invalid opcodes caused A68k
  1249.         to get lost when returning to the outer    source file.
  1250.         (Colin Fox)
  1251.  
  1252.           -    Large values of    -w (over 6000 or so) would cause
  1253.         a visit    from the Guru.    The work field in HashIt
  1254.         was overflowing    and going negative.  Changing it
  1255.         to unsigned corrected the problem.  (Colin Fox)
  1256.  
  1257.           -    Although user macros are no longer displayed when
  1258.         -q is a    negative number, the calling file's name
  1259.         was still being    displayed at the end of    the macro.
  1260.  
  1261.  
  1262. Version    2.3 (Charlie Gibbs, November 21, 1988)
  1263.  
  1264.     The following enhancements have    been added:
  1265.  
  1266.           -    All file I/O has been rewritten    to use level 1 I/O
  1267.         (open, creat, close, read, write, and lseek) instead
  1268.         of level 2 I/O.     A68k now does its own buffering and
  1269.         unbuffering to reduce system overhead and increase speed.
  1270.         (Bruce Dawson)
  1271.  
  1272.           -    All assembler directives have been incorporated    into
  1273.         the opcode table.  Since the opcode search now looks
  1274.         up directives as well, speed is    increased.
  1275.  
  1276.           -    Miscellaneous code optimization    for additional speed.
  1277.  
  1278.  
  1279. Version    2.2 (Charlie Gibbs, November 4,    1988)
  1280.  
  1281.     The following bugs in version 2.1 have been corrected:
  1282.  
  1283.           -    Macro definitions within an INCLUDE file were
  1284.         disabling the test for skipping    the file on pass 2.
  1285.  
  1286.           -    Errors encountered in an INCLUDE file on pass 1
  1287.         were not disabling the skip of the file    on pass    2 -
  1288.         the pertinent error messages could not appear.
  1289.  
  1290.           -    XDEF information and optional symbol table dumps were
  1291.         not being written to the object    code file for any
  1292.         hunks that did not contain relocatable code or data.
  1293.         (Colin Fox)
  1294.  
  1295.     The following enhancements have    been added:
  1296.  
  1297.           -    If the -q option is specified as a negative value,
  1298.         user macros are    no longer included in line number
  1299.         displays, reducing clutter.
  1300.  
  1301.           -    Some source code has been re-arranged to reduce    size.
  1302.  
  1303.  
  1304. Version    2.1 (Charlie Gibbs, November 1,    1988)
  1305.  
  1306.     The following bugs in version 2.00 have    been corrected:
  1307.  
  1308.           -    Macro definitions that span two    chunks of memory
  1309.         were causing garbage and probably a crash when
  1310.         the macro was being expanded.  Pointers    were not
  1311.         being handled properly when linking the    two chunks.
  1312.  
  1313.           -    Statements such    as EQU and SET were not    being flagged
  1314.         as illegal forward references if referencing a label
  1315.         defined    on the same line, e.g.
  1316.             LABEL    SET    LABEL+1
  1317.  
  1318.           -    The position within macros and INCLUDE files was
  1319.         sometimes out by one line when reported    in error
  1320.         messages (and the new feature of the -q    switch).
  1321.  
  1322.     The following enhancements have    been added:
  1323.  
  1324.           -    If the -q option is specified as a negative value,
  1325.         line numbers will be displayed as positions within
  1326.         the current module (whose name is also displayed),
  1327.         rather than a total statement count.  (Bruce Dawson)
  1328.  
  1329.           -    INCLUDE    files can be skipped on    pass 2 even if they
  1330.         contain    SET statements - the values of all symbols
  1331.         SET in the INCLUDE file    are stored (as at the end
  1332.         of the file) in    a separate table and are patched
  1333.         when the INCLUDE file is skipped.  (Bruce Dawson)
  1334.  
  1335.  
  1336. Version    2.00 (Charlie Gibbs, October 26, 1988)
  1337.  
  1338.     The following bugs in version 1.24 have    been corrected:
  1339.  
  1340.           -    The last digit of the statement    number display
  1341.         (lengthened in version 1.24) was not being erased
  1342.         before displaying error    messages.
  1343.  
  1344.           -    A68k would go into a loop if a user macro was
  1345.         missing    an ENDC    directive.  This error is now
  1346.         flagged    (see below).
  1347.  
  1348.     The following enhancements have    been added:
  1349.  
  1350.           -    The highest statement number displayed at the end of
  1351.         each pass is now left on the screen.  This means that,
  1352.         at the end of pass 1, you can always see how many lines
  1353.         A68k will have to process in pass 2, giving an idea of
  1354.         how how    much longer you    have to    wait.  (Colin Fox)
  1355.  
  1356.           -    The symbol table is now    built using a hashing algorithm.
  1357.         This eliminates    the slowdown that occurs in pass 1 as
  1358.         the symbol table grows,    due to the old insertion process.
  1359.         (Bruce Dawson)
  1360.  
  1361.           -    If A68k    terminates abnormally for any reason (such as
  1362.         insufficient memory) the object    file is    scratched
  1363.         (unless    the -k option is set).    (Bruce Dawson)
  1364.  
  1365.           -    Any INCLUDE files which    cannot be found    are flagged
  1366.         as errors in pass 1, and the assembly is aborted
  1367.         at the end of pass 1.  (Bruce Dawson)
  1368.  
  1369.           -    Missing    ENDC directives    are flagged in macro expansions.
  1370.         Also, missing or unpaired ENDC directives in user macros
  1371.         are flagged.
  1372.  
  1373.           -    If an INCLUDE file doesn't generate any code and no
  1374.         listing    file is    required, it won't be read again in
  1375.         pass 2.     The statement numbers will be bumped to keep
  1376.         in proper alignment.  This can really speed up
  1377.         assemblies that    INCLUDE    lots of    equates.  (Colin Fox)
  1378.  
  1379.  
  1380. Version    1.24 (Charlie Gibbs, October 11, 1988)
  1381.  
  1382.     The following bugs in version 1.23 have    been corrected:
  1383.  
  1384.           -    MOVEA to a data    register was not being flagged,    even
  1385.         though all other invalid addressing modes were.
  1386.  
  1387.           -    Attempts to ORG    out of the current hunk    (including
  1388.         to an absolute address)    were not being flagged.     (E. Lenz)
  1389.  
  1390.           -    If the size of the bottom of the primary heap (symbols
  1391.         and macro text)    exceeded 32K, any further macro
  1392.         definitions would expand as endless garbage.  (Colin Fox)
  1393.  
  1394.           -    If the size of the bottom of the primary heap (symbols
  1395.         and macro text)    exceeded 64K, any further external
  1396.         symbols    (XDEF) would be    flagged    as relocatability
  1397.         errors upon each reference.  (Colin Fox)
  1398.  
  1399.     The following enhancements have    been added:
  1400.  
  1401.           -    Where statement    numbers    are displayed as fixed-length
  1402.         fields,    their maximum length has been increased
  1403.         from 4 digits to 5.  (Colin Fox)
  1404.  
  1405.           -    The PUBLIC directive has been implemented.
  1406.         As with    the Aztec assembler, any labels    defined    as
  1407.         PUBLIC will be treated as XDEF if defined within
  1408.         the current module, and    XREF otherwise.     (Jeff Lydiatt)
  1409.  
  1410.  
  1411. Version    1.23 (Charlie Gibbs, September 20, 1988)
  1412.  
  1413.     The following bugs in version 1.22 have    been corrected:
  1414.  
  1415.           -    The test for a third operand was producing erroneous
  1416.         error messages on instructions whose second operand
  1417.         was in immediate mode.    The '#' was not being taken
  1418.         into account, since it is not copied to    DestOp.
  1419.  
  1420.  
  1421. Version    1.22 (Charlie Gibbs, August 31,    1988)
  1422.  
  1423.     The following bugs in version 1.21 have    been corrected:
  1424.  
  1425.           -    Expressions of the form    R-A, where R is    a relocatable
  1426.         term or    expression and A is an absolute    term or
  1427.         expression, were being flagged as relocation errors.
  1428.         This was due to    a bug in the routine which should
  1429.         (but did not) flag expressions of the form A-R.
  1430.         (David Ashley)
  1431.  
  1432.           -    Instructions with three    operands were not being
  1433.         flagged    as errors.  This can be    caused by an extra
  1434.         comma being typed in the instruction, as in:
  1435.             BTST #0,state+3,(a5)
  1436.         The second comma should    not be present.     (David    Ashley)
  1437.  
  1438.     The following enhancements have    been added:
  1439.  
  1440.           -    Excess spacing has been    removed    from the listing file.
  1441.         These changes are similar to those already made    to the
  1442.         console    output (probably at about version 1.05).
  1443.  
  1444.           -    If the first statement in the source file is TTL or
  1445.         PAGE, an empty page is no longer produced at the
  1446.         start of the listing.
  1447.  
  1448.  
  1449. Version    1.21 (Charlie Gibbs, July 29, 1988)
  1450.  
  1451.     The following bugs in version 1.2 have been corrected:
  1452.  
  1453.           -    The instruction
  1454.             BTST.L    #8,D0
  1455.         had a long-word    value generated    for the    bit number.
  1456.         This bug also applies to BSET, BCLR, and BCHG.
  1457.         The .L specification is    now ignored.  (Ulf Nordquist)
  1458.  
  1459.  
  1460. Version    1.2 (Charlie Gibbs, July 19, 1988)
  1461.  
  1462.     The following bugs in version 1.12 have    been corrected:
  1463.  
  1464.           -    A reference to the label of the    current    instruction
  1465.         was being converted to PC-relative on pass 2 but not
  1466.         on pass    1.  This was causing phase errors.  The    label
  1467.         hasn't been added to the symbol table at the time the
  1468.         instruction is processed.  Conversion to PC-relative
  1469.         addressing will    now not    be attempted in    this case,
  1470.         although references to * can and will be converted.
  1471.  
  1472.           -    All string-type    DC statements, regardless of length,
  1473.         were being treated as DC.B.  For example, DC.L 'A'
  1474.         would generate only one    byte of    object code.
  1475.         (Gerald    Hull)
  1476.  
  1477.           -    DC.W and DC.B statements were not being    checked    to
  1478.         ensure that their values would fit into    a word or
  1479.         a byte respectively.
  1480.  
  1481.           -    If a comment line had white space preceding the
  1482.         asterisk, A68k would hang.  Actually, it was
  1483.         interpreting the asterisk as an    opcode and trying
  1484.         to open    a macro    file called "*".  Since under
  1485.         AmigaDOS such a    file is    the console, A68k was
  1486.         actually waiting for console input.
  1487.  
  1488.           -    If an instruction with no operands (such as RTS
  1489.         or NOP)    followed MOVE.L    #rel,D0    where "rel" was
  1490.         a relocatable symbol, the RTS (etc.) would have
  1491.         its nonexistent    operands flagged as invalid.
  1492.  
  1493.           -    SECTION    names enclosed in quotes were not being
  1494.         handled    correctly.
  1495.  
  1496.           -    Source modules that did    not generate any code, data,
  1497.         or BSS areas, but only defined symbols,    such as
  1498.             label    equ    4
  1499.                 xdef    label
  1500.                 end
  1501.         were generating    incomplete object modules.
  1502.  
  1503.     The following enhancements have    been added:
  1504.  
  1505.           -    Jeff's experimental hunk code (prefixing hunk names
  1506.         with a sequence    number before adding to    the symbol
  1507.         table) has been    permanently incorporated.  It seems
  1508.         to work    better with BLink on programs that have
  1509.         hunks continued    farther    on in the source code.
  1510.         (Jeff Lydiatt)
  1511.  
  1512.           -    The macro parameter \0,    which is replaced by the
  1513.         size specification in the macro    call (B, W, or L,
  1514.         defaulting to W) is now    supported.  (Gerald Hull)
  1515.  
  1516.           -    Operands of the    form 0(An) will    be treated as (An).
  1517.         (Bruce Dawson)
  1518.  
  1519.  
  1520. Version    1.12 (Charlie Gibbs, May 25, 1988)
  1521.  
  1522.     The following bugs in version 1.11 have    been corrected:
  1523.  
  1524.           -    If an instruction with no operands (e.g. RTS)
  1525.         followed a MOVE.L #label,D0 the    RTS would be
  1526.         flagged    with a relocatability error.  Src.Mode
  1527.         and Dest.Mode were not being cleared.  (Colin Fox)
  1528.  
  1529.  
  1530. Version    1.11 (Charlie Gibbs, April 6, 1988)
  1531.  
  1532.     The following bugs in version 1.10 have    been corrected:
  1533.  
  1534.           -    A68k would go into a loop while    processing the
  1535.         arguments of a macro call, if these arguments are
  1536.         followed by comments separated from the    arguments
  1537.         by one or more tab characters, and the -t switch
  1538.         is specified on    the command line.  All tests for
  1539.         blanks have been replaced by calls to isspace().
  1540.  
  1541.           -    The operand alignment checks added in version 1.06
  1542.         were erroneously testing the following instructions:
  1543.             BCHG
  1544.             BCLR
  1545.             BSET
  1546.             BTST
  1547.             NBCD
  1548.             Scc
  1549.             TAS
  1550.         These instructions are now exempt from alignment checking.
  1551.  
  1552.     The following enhancements have    been added:
  1553.  
  1554.           -    A listing file name can    now be specified with the
  1555.         -x switch; it is no longer necessary to    specify
  1556.         both the -l and    -x switches to produce a cross-
  1557.         reference listing with a name other than the default.
  1558.  
  1559.           -    DS statements with more    than one operand are
  1560.         flagged    and ignored (in    case they should be DC).
  1561.  
  1562.           -    A character string used    as a numeric value is
  1563.         flagged    and set    to zero    if it is more than four
  1564.         characters long.
  1565.  
  1566.  
  1567. Version    1.10 (Charlie Gibbs, March 20, 1988)
  1568.  
  1569.     The following bugs in version 1.07 have    been corrected:
  1570.  
  1571.           -    BSS sections were not being written to the object
  1572.         code file except for a BSS section at the end of
  1573.         a program.  This is due    to a bug in the    code added
  1574.         in version 1.05    to overwrite null sections.
  1575.  
  1576.           -    If a source module contained a mixture of lengths
  1577.         (8, 16,    or 32 bits) in external    references (XREF)
  1578.         to the same label, all references were being treated
  1579.         as if they has the length of the first reference.
  1580.  
  1581.     The following enhancements have    been added:
  1582.  
  1583.           -    DS operands that are either a forward references
  1584.         or relocatable are now flagged.
  1585.  
  1586.           -    Short branches (Bcc.S, including BRA and BSR) to
  1587.         the next instruction (i.e. a displacement of zero)
  1588.         are illegal - the processor takes the displacement
  1589.         from the next word.  Attempts to generate a short
  1590.         displacement of    zero are now flagged.
  1591.  
  1592.  
  1593. Version    1.07 (Charlie Gibbs, March 11, 1988)
  1594.  
  1595.     The following bugs in version 1.06 have    been corrected:
  1596.  
  1597.           -    Instructions that take no operands (such as RTS)
  1598.         were being flagged if they had comments    that were
  1599.         not preceded by    a semicolon.
  1600.  
  1601.     The following enhancements have    been added:
  1602.  
  1603.           -    The following synonyms have been added:
  1604.             CSEG  for CODE (Aztec compatibility)
  1605.             DSEG  for DATA     "          "
  1606.             ENDIF for ENDC (Assempro compatibility)
  1607.             =     for EQU       "           "
  1608.             |     for !       "           "
  1609.  
  1610.           -    Strings    and character values may be delimited by
  1611.         either apostrophes (') or quotation marks (").
  1612.         The character not used as a delimiter can be used
  1613.         within the string without doubling it.    For example,
  1614.             DC.B    "This is Charlie's assembler"
  1615.         produces the same code as
  1616.             DC.B    'This is Charlie''s assembler"
  1617.  
  1618.           -    The object code    file will be scratched if any errors
  1619.         were found, unless the -k (keep) flag is set.
  1620.         (Bruce Dawson)
  1621.  
  1622.           -    The symbol .A68K is automatically defined at the
  1623.         beginning of each assembly as a    SET symbol with    an
  1624.         absolute value of 1.  This enables programs to check
  1625.         whether    they're being assembled by this assembler.
  1626.         (Jeff Lydiatt)
  1627.  
  1628.           -    The symbol table insertion routine has been
  1629.         greatly    speeded    up.
  1630.  
  1631.  
  1632. Version    1.06 (Charlie Gibbs, March 6, 1988)
  1633.  
  1634.     The following bugs in version 1.05 have    been corrected:
  1635.  
  1636.           -    Lines skipped by IFxx/ENDC were    not being counted
  1637.         in the line number given in error messages.
  1638.  
  1639.           -    DATA and BSS sections may be unnamed, or have names
  1640.         the same as CODE sections.  Honest, I thought section
  1641.         names had to be    unique even across types.
  1642.  
  1643.           -    CHIP and FAST options on the CODE, DATA, and BSS
  1644.         synonyms for the SECTION directive were    not being
  1645.         handled    correctly.
  1646.  
  1647.           -    XDEF records and symbol    table records (if desired)
  1648.         were not being produced    for symbols defined ahead
  1649.         of the first object-code producing instruction.
  1650.  
  1651.     The following enhancements have    been added:
  1652.  
  1653.           -    The CNOP instruction can now force alignment
  1654.         relative to any    boundary up to 128 bytes.
  1655.         The second operand must    still be a power of 2.
  1656.  
  1657.           -    The -q switch has been added to    change the frequency
  1658.         with which progress reports (current line number) are
  1659.         displayed on the console.  The default remains at
  1660.         every 10 lines (-q10).    If you specify -q (no interval)
  1661.         or -q0 the line    number displays    will be    suppressed.
  1662.         This will make assemblies run slightly faster due to
  1663.         reduced    console    I/O.  (Bill Henning)
  1664.  
  1665.           -    The -t switch has been added to    keep any tabs in the
  1666.         source file when producing the listing file, as    well as
  1667.         generating tabs    elsewhere whenever possible.  This
  1668.         speeds up assemblies and gives smaller listing files,
  1669.         but such listing files cannot be displayed on devices
  1670.         that do    not assume a tab stop in every 8th position.
  1671.         (Bruce Dawson)
  1672.  
  1673.           -    Any single-operand instruction with two    operands,
  1674.         and any    no-operand instruction with any    operands,
  1675.         will be    flagged.
  1676.  
  1677.           -    Relocatable 8- or 16-bit immediate operands
  1678.         will be    flagged.  They blow up BLink.
  1679.  
  1680.           -    Named local labels are now supported.  Their names
  1681.         are formed in the same way as normal labels, but are
  1682.         then preceded by a backslash.  Their scope is the
  1683.         same as    normal local labels (nnn$).  (Colin Fox)
  1684.  
  1685.           -    An alignment error will    be flagged in the following cases:
  1686.             Odd    displacement on    a LINK instruction
  1687.             Bcc    or DBcc    to an odd address
  1688.             In any word    or long-word instruction, any operand
  1689.               using the    following addressing modes:
  1690.             Address    register indirect with displacement
  1691.             Address    register indirect with index and displacement
  1692.             Absolute short
  1693.             Absolute long
  1694.             Program    counter    indirect with displacement
  1695.             Program    counter    indirect with index and    displacement
  1696.             LEA    and PEA    instructions are exempt    from these tests.
  1697.  
  1698.           -    If a section is    found to contain no data, A68k will
  1699.         back up    to its beginning and overwrite it with the
  1700.         next section.  The result is that null sections
  1701.         will no    longer appear in the object file.
  1702.  
  1703.  
  1704. Version    1.05 (Charlie Gibbs, October 30, 1987)
  1705.  
  1706.     The following bugs in version 1.04 have    been corrected:
  1707.  
  1708.           -    If a section was continued later in the    program, e.g.
  1709.  
  1710.             SECTION    prog,CODE
  1711.               <code>
  1712.             SECTION    variables,BSS
  1713.               <DS statements>
  1714.             SECTION    prog,CODE
  1715.               <more    code>
  1716.  
  1717.         bad relocation information was being generated for
  1718.         the continuation of the    SECTION.  This bug was left
  1719.         over from version 1.03.
  1720.  
  1721.     The following enhancements have    been added:
  1722.  
  1723.           -    All console output except for error messages is    now
  1724.         sent to    stderr - this enables stdout to    be redirected,
  1725.         producing an error file.
  1726.  
  1727.           -    Console    (stderr) output    has been modified to require
  1728.         fewer lines on the screen.
  1729.  
  1730.           -    If an error occurs while expanding a macro or INCLUDE
  1731.         file, the position of the call in each outer file is
  1732.         given along with the position in the current (innermost)
  1733.         file.  Tracing continues until the outermost file (i.e.
  1734.         the original source file) is reached.
  1735.  
  1736.  
  1737. Version    1.04 (Charlie Gibbs, October 21, 1987)
  1738.  
  1739.     The following bugs in version 1.03 have    been corrected:
  1740.  
  1741.           -    MOVE was being converted to MOVEQ regardless of
  1742.         operand    size - this conversion is legal    only
  1743.         for longword MOVEs.
  1744.  
  1745.           -    Modifications to version 1.03 caused bad relocatable
  1746.         entries    to be generated.
  1747.  
  1748.  
  1749. Version    1.03 (Charlie Gibbs, October 14, 1987)
  1750.  
  1751.     The following bugs in version 1.02 have    been corrected:
  1752.  
  1753.           -    The following situation    was causing phase errors:
  1754.  
  1755.                 xdef    label
  1756.                 bra    label
  1757.                  .
  1758.                 <at    least 128 bytes    of object code>
  1759.                  .
  1760.             label:
  1761.  
  1762.         (The XDEF was fooling A68k into    thinking that "label"
  1763.         was defined within 128 bytes of    the BRA    instruction
  1764.         on pass    1, although on pass 2 it knew better.
  1765.  
  1766.           -    If the first operand of    an two-operand executable
  1767.         instruction contained a    character term containing a
  1768.         left or    right parenthesis, it would generate error
  1769.         messages and be    incorrectly evaluated.
  1770.  
  1771.           -    Labels that don't begin in column 1 (denoted by a
  1772.         trailing colon)    caused a Guru Meditation.
  1773.  
  1774.           -    Certain    ADD and    SUB instructions using PC-relative
  1775.         addressing may cause phase errors.  If the displacement
  1776.         is in the range    1 to 8 inclusive, the instruction was
  1777.         erroneously converted to ADDQ or SUBQ during pass 2.
  1778.  
  1779.     The following enhancements have    been added:
  1780.  
  1781.           -    The -z option has been added to    display    the
  1782.         current    source program line on stdout as it
  1783.         is read, optionally over a given range.
  1784.         This feature is    provided for debugging purposes.
  1785.  
  1786.           -    Bcc, BSR, and DBcc to labels in    other than the current
  1787.         section    is now supported.  A 16-bit relocation entry
  1788.         will be    generated for each such    reference.
  1789.  
  1790.           -    PC relative mode will be generated for backward
  1791.         references to labels within the    current    CODE section
  1792.         if legal for the current instruction.  Forward
  1793.         references will    not be converted, since    there is
  1794.         no way of telling which    section    the label is in
  1795.         during pass 1.
  1796.  
  1797.           -    The cumulative sizes of    all sections by    type (i.e.
  1798.         CODE, DATA, and    BSS) will be displayed at the end
  1799.         of the listing file and    the console display.
  1800.         (Bruce Dawson)
  1801.  
  1802.           -    In the symbol table dump, section names    will no
  1803.         longer be indicated just as SECTION, but rather
  1804.         as CODE, DATA, or BSS, depending on type.
  1805.  
  1806.  
  1807. Version    1.02 (Charlie Gibbs, September 9, 1987)
  1808.  
  1809.     The following bugs in version 1.01 have    been corrected:
  1810.  
  1811.           -    Duplicate labels were not being    flagged.
  1812.  
  1813.           -    XDEF symbols were not being dumped to the
  1814.         object code file when the -d option was    set.
  1815.  
  1816.     The following enhancements have    been added:
  1817.  
  1818.           -    A header file is now supported.     If the    parameter
  1819.         -h<filespec> is    included on the    command    line, the
  1820.         specified file will be included    as if the source
  1821.         file's first line was " include <filespec>".
  1822.         The file specification may include a path name,
  1823.         although the include path names    given by the
  1824.         -i parameter (if any) will also    be searched.
  1825.  
  1826.           -    An equate file can now be produced.  If    the parameter
  1827.         -e<filespec> is    included on the    command    line, a    file
  1828.         will be    written    containing EQU statements for any
  1829.         symbol whose value is absolute.     If -e is specified
  1830.         without    <filespec>, the    name of    the file will be
  1831.         formed in the same way as the list file, except    with
  1832.         an extension of    ".equ".  (Bruce Dawson)
  1833.  
  1834.     The following changes have been    made to    existing logic:
  1835.  
  1836.           -    No symbol table    dump will be produced unless the
  1837.         -x (cross-reference) switch is set.  Formerly a
  1838.         symbol table dump was always produced, with only
  1839.         the cross-reference portion optional.
  1840.  
  1841.  
  1842. Version    1.01 (Charlie Gibbs, August 20,    1987)
  1843.  
  1844.     The following bugs in version 1.00 have    been corrected:
  1845.  
  1846.           -    Long-word constants and    storage    areas were being
  1847.         aligned    on a double-word boundary.  The    only place
  1848.         where double-word alignment is now forced is at    a
  1849.         break between SECTIONs,    since the length of an
  1850.         AmigaDOS hunk must be a    multiple of 4 bytes.
  1851.         (CNOP 0,4 can still be used if double-word
  1852.         alignment is desired by    the programmer.)
  1853.  
  1854.           -    If a label on an END statement or the first statement
  1855.         of a SECTION was named in an XDEF statement, it    would
  1856.         not be written to the object code file.     The latter
  1857.         case includes both the label of    a SECTION directive
  1858.         and the    label of the first executable instruction in
  1859.         the absence of any SECTION directives (defaulting to
  1860.         an unnamed CODE    section).  In the final    case (default
  1861.         unnamed    CODE section), references to XREF symbols
  1862.         in the first statement would also not be written
  1863.         to the object code file.
  1864.  
  1865.           -    If the last statement in the source file was not
  1866.         terminated with    a newline character (premature EOF),
  1867.         it was being ignored altogether.
  1868.  
  1869.           -    A register list    as the source operand of a MOVE
  1870.         instruction was    not being flagged as an    error.
  1871.         (MOVE to a register list was being flagged, however.)
  1872.  
  1873.           -    MOVE from USP was generating incorrect code.  Also,
  1874.         MOVE from SR or    CCR to an address register was
  1875.         generating incorrect code rather than being flagged.
  1876.  
  1877.  
  1878. Version    1.00 (Charlie Gibbs, June 18, 1987) - initial release
  1879. SHAR_EOF
  1880. cat << \SHAR_EOF > A68k2do.txt
  1881. A68k - things to do as of January 10, 1989
  1882.  
  1883.  
  1884. *** BUGS ***
  1885.  
  1886. (There are no known bugs at this time.)
  1887.  
  1888.  
  1889. *** ENHANCEMENTS ***
  1890.  
  1891. Implement an ARexx interface to    an editor (e.g.    CED) for debugging.
  1892. Possibly commands could    be read    from a configuration file so that
  1893. A68k could be customized to any    editor's commands and port name.
  1894.  
  1895. Improve    the small code / small data option - study linker documentation!
  1896.  
  1897. Wild optimizations? (e.g. MOVE.W #0,D0 -> CLR.W    D0)
  1898.  
  1899. Treat (An,Dn) as 0(An,Dn)?  Or just leave for 68020 upgrade?
  1900.  
  1901. Add 68010/68020    support.
  1902. SHAR_EOF
  1903. cat << \SHAR_EOF > Makefile
  1904. # Simple makefile to compile and link the A68k Assembler.
  1905. # Created 23Jun87 by J.A. Lydiatt
  1906. #
  1907.  
  1908. OBJ=    A68kmain.o Opcodes.o Operands.o Adirect.o A68kmisc.o\
  1909.     Symtab.o Codegen.o wb_parse.o
  1910.  
  1911. SHARLIB1= A68k.doc makefile A68kdef.h A68kglb.h A68kmain.c Opcodes.c Operands.c\
  1912.     Adirect.c A68kmisc.c Symtab.c Codegen.c wb_parse.c isspace.c
  1913.  
  1914. SRC=    A68kmain.c Opcodes.c Operands.c Adirect.c A68kmisc.c\
  1915.     Symtab.c Codegen.c wb_parse.c isspace.c
  1916.  
  1917. SHARLIB2= A68k.uue
  1918.  
  1919. .c.o:
  1920.     cc +x3 -Z3000 -o $*.o $*.c
  1921.  
  1922. A68k:    $(OBJ) 
  1923.     ln -o A68k $(OBJ) -lc
  1924.  
  1925. $(OBJ):    A68kdef.h A68kglb.h
  1926.  
  1927. #
  1928. # Note: Manx's makefile seems to have a bug that forbids indirection
  1929. #    such as "shar >lib a.c  b.c c.c"
  1930. #    however "make >lib" seems to work fine if you edit out the
  1931. #    commands make echos as it proceeds through the makefile.
  1932. #
  1933. #    Try make >ram:shardcp Archive 
  1934. #
  1935.  
  1936. Archive:
  1937.     shar $(SHARLIB1)
  1938.     shar $(SHARLIB2)
  1939.  
  1940. Lint:
  1941.     lint -iAztec:include Aztec:Stdlib.c Aztec:Defaults.c $(SRC)
  1942. SHAR_EOF
  1943. cat << \SHAR_EOF > Makefile.azt
  1944. # Simple makefile to compile and link the A68k Assembler.
  1945. # Created 23Jun87 by J.A. Lydiatt
  1946. #
  1947.  
  1948. OBJ=    A68kmain.o Opcodes.o Operands.o Adirect.o A68kmisc.o\
  1949.     Symtab.o Codegen.o wb_parse.o
  1950.  
  1951. SHARLIB1= A68k.doc makefile A68kdef.h A68kglb.h A68kmain.c Opcodes.c Operands.c\
  1952.     Adirect.c A68kmisc.c Symtab.c Codegen.c wb_parse.c isspace.c
  1953.  
  1954. SRC=    A68kmain.c Opcodes.c Operands.c Adirect.c A68kmisc.c\
  1955.     Symtab.c Codegen.c wb_parse.c isspace.c
  1956.  
  1957. SHARLIB2= A68k.uue
  1958.  
  1959. .c.o:
  1960.     cc +x3 -Z3000 -o $*.o $*.c
  1961.  
  1962. A68k:    $(OBJ) 
  1963.     ln -t -o A68k $(OBJ) -lc
  1964.  
  1965. $(OBJ):    A68kdef.h A68kglb.h
  1966.  
  1967. #
  1968. # Note: Manx's makefile seems to have a bug that forbids indirection
  1969. #    such as "shar >lib a.c  b.c c.c"
  1970. #    however "make >lib" seems to work fine if you edit out the
  1971. #    commands make echos as it proceeds through the makefile.
  1972. #
  1973. #    Try make >ram:shardcp Archive 
  1974. #
  1975.  
  1976. Archive:
  1977.     shar $(SHARLIB1)
  1978.     shar $(SHARLIB2)
  1979.  
  1980. Lint:
  1981.     lint -iAztec:include Aztec:Stdlib.c Aztec:Defaults.c $(SRC)
  1982. SHAR_EOF
  1983. cat << \SHAR_EOF > Makefile.dbg
  1984. # Simple makefile to compile and link the A68k Assembler.
  1985. # Created 23Jun87 by J.A. Lydiatt
  1986. #
  1987.  
  1988. OBJ=    A68kmain.o Opcodes.o Operands.o Adirect.o A68kmisc.o\
  1989.     Symtab.o Codegen.o wb_parse.o isspace.o
  1990.  
  1991. SHARLIB1= A68k.doc makefile A68kdef.h A68kglb.h A68kmain.c Opcodes.c Operands.c\
  1992.     Adirect.c A68kmisc.c Symtab.c Codegen.c wb_parse.c isspace.c
  1993.  
  1994. SRC=    A68kmain.c Opcodes.c Operands.c Adirect.c A68kmisc.c\
  1995.     Symtab.c Codegen.c wb_parse.c isspace.c
  1996.  
  1997. SHARLIB2= A68k.uue
  1998.  
  1999. .c.o:
  2000.     cc -n -Z3000 -o $*.o $*.c
  2001.  
  2002. A68k:    $(OBJ)
  2003.     ln -g -o A68k $(OBJ) -lc
  2004.  
  2005. $(OBJ):    A68kdef.h A68kglb.h
  2006.  
  2007. #
  2008. # Note: Manx's makefile seems to have a bug that forbids indirection
  2009. #    such as "shar >lib a.c  b.c c.c"
  2010. #    however "make >lib" seems to work fine if you edit out the
  2011. #    commands make echos as it proceeds through the makefile.
  2012. #
  2013. #    Try make >ram:shardcp Archive 
  2014. #
  2015.  
  2016. Archive:
  2017.     shar $(SHARLIB1)
  2018.     shar $(SHARLIB2)
  2019.  
  2020. Lint:
  2021.     lint -iAztec:include Aztec:Stdlib.c Aztec:Defaults.c $(SRC)
  2022. SHAR_EOF
  2023. cat << \SHAR_EOF > Makefile.pdc
  2024. # Simple makefile to compile and link the A68k Assembler.
  2025. # Created 23Jun87 by J.A. Lydiatt
  2026. #
  2027.  
  2028. OBJ=    A68kmain.o Opcodes.o Operands.o Adirect.o A68kmisc.o\
  2029.     Symtab.o Codegen.o wb_parse.o isspace.o
  2030.  
  2031. SHARLIB1= A68k.doc makefile A68kdef.h A68kglb.h A68kmain.c Opcodes.c Operands.c\
  2032.     Adirect.c A68kmisc.c Symtab.c Codegen.c wb_parse.c isspace.c
  2033.  
  2034. SRC=    A68kmain.c Opcodes.c Operands.c Adirect.c A68kmisc.c\
  2035.     Symtab.c Codegen.c wb_parse.c isspace.c
  2036.  
  2037. SHARLIB2= A68k.uue
  2038.  
  2039. .c.o:
  2040.     cc -P -qvd0: -c $*.c
  2041.  
  2042. A68k:    $(OBJ) 
  2043.     cc -o A68k $(OBJ)
  2044.  
  2045. $(OBJ):    A68kdef.h A68kglb.h
  2046.  
  2047. #
  2048. # Note: Manx's makefile seems to have a bug that forbids indirection
  2049. #    such as "shar >lib a.c  b.c c.c"
  2050. #    however "make >lib" seems to work fine if you edit out the
  2051. #    commands make echos as it proceeds through the makefile.
  2052. #
  2053. #    Try make >ram:shardcp Archive 
  2054. #
  2055.  
  2056. Archive:
  2057.     shar $(SHARLIB1)
  2058.     shar $(SHARLIB2)
  2059.  
  2060. Lint:
  2061.     lint -iAztec:include Aztec:Stdlib.c Aztec:Defaults.c $(SRC)
  2062. SHAR_EOF
  2063. cat << \SHAR_EOF > wb_parse.c
  2064. _wb_parse(){}
  2065. SHAR_EOF
  2066. #    End of shell archive
  2067. exit 0
  2068. -- 
  2069. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2070. Have five nice days.
  2071.